package com.bai.ad.service.impl;

import com.bai.ad.constant.Constants;
import com.bai.ad.dao.AdPlanRepository;
import com.bai.ad.dao.AdUnitRepository;
import com.bai.ad.dao.CreativeRepository;
import com.bai.ad.dao.unit_condition.AdUnitDistrictRepository;
import com.bai.ad.dao.unit_condition.AdUnitItRepository;
import com.bai.ad.dao.unit_condition.AdUnitKeywordRepository;
import com.bai.ad.dao.unit_condition.CreativeUnitRepository;
import com.bai.ad.entity.AdPlan;
import com.bai.ad.entity.AdUnit;
import com.bai.ad.entity.unit_condition.AdUnitDistrict;
import com.bai.ad.entity.unit_condition.AdUnitIt;
import com.bai.ad.entity.unit_condition.AdUnitKeyword;
import com.bai.ad.entity.unit_condition.CreativeUnit;
import com.bai.ad.service.IAdUnitService;
import com.bai.ad.vo.*;
import com.bao.ad.exception.AdException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * ClassName AdUnitServiceImpl
 *
 * @author Bai
 * @version 1.0
 * @date 2019/2/20 0020 下午 22:01
 **/

@Slf4j
@Service
public class AdUnitServiceImpl implements IAdUnitService {

    private final AdPlanRepository adPlanRepository;
    private final AdUnitRepository adUnitrepository;
    private final AdUnitItRepository adUnitItRepository;
    private final AdUnitKeywordRepository adUnitKeywordRepository;
    private final AdUnitDistrictRepository adUnitDistrictRepository;
    private final CreativeRepository creativeRepository;
    private final CreativeUnitRepository creativeUnitRepository;

    @Autowired
    public AdUnitServiceImpl(AdPlanRepository adPlanRepository,
                             AdUnitRepository adUnitrepository,
                             AdUnitItRepository adUnitItRepository,
                             AdUnitKeywordRepository adUnitKeywordRepository,
                             AdUnitDistrictRepository adUnitDistrictRepository,
                             CreativeRepository creativeRepository,
                             CreativeUnitRepository creativeUnitRepository) {
        this.adPlanRepository = adPlanRepository;
        this.adUnitrepository = adUnitrepository;
        this.adUnitItRepository = adUnitItRepository;
        this.adUnitKeywordRepository = adUnitKeywordRepository;
        this.adUnitDistrictRepository = adUnitDistrictRepository;
        this.creativeRepository = creativeRepository;
        this.creativeUnitRepository = creativeUnitRepository;
    }


    @Override
    public AdUnitResponse createUnit(AdUnitRequest request) throws AdException {

        if(!request.createValidate()){
            throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
        }

        Optional<AdPlan> adPlan = adPlanRepository.findById(request.getPlanId());

        if(!adPlan.isPresent()){
            throw new AdException(Constants.ErrorMsg.CAN_NOT_FIND_RECORD);
        }

        AdUnit oldAdUnit = adUnitrepository.findByPlanIdAndUnitName(request.getPlanId(), request.getUnitName());

        if(null != oldAdUnit){
            throw new AdException(Constants.ErrorMsg.SAME_NAME_UNIT_ERROR);
        }

        AdUnit newAdUnit = adUnitrepository.save(new AdUnit(request.getPlanId(), request.getUnitName(),
                request.getPositionType(), request.getBudget()));

        return new AdUnitResponse(newAdUnit.getId(), newAdUnit.getUnitName());
    }

    @Override
    public AdUnitKeywordResponse createUnitKeyword(AdUnitKeywordRequest request) throws AdException {

        List<Long> unitId = request.getUnitKeywords().stream()
                .map(AdUnitKeywordRequest.UnitKeyword::getUnitId)
                .collect(Collectors.toList());

        if(!isRelatedUnitExits(unitId)){
            throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
        }

        List<Long> ids = Collections.emptyList();

        List<AdUnitKeyword> unitKeyWords = new ArrayList<>();
        if(!CollectionUtils.isEmpty(request.getUnitKeywords())){
            request.getUnitKeywords().forEach(i -> unitKeyWords.add(
                    new AdUnitKeyword(i.getUnitId(), i.getKeyword())
            ));
            ids = adUnitKeywordRepository.saveAll(unitKeyWords).stream()
                    .map(AdUnitKeyword::getId)
                    .collect(Collectors.toList());
        }
        return new AdUnitKeywordResponse(ids);
    }

    @Override
    public AdUnitItResponse createUnitIt(AdUnitItRequest request) throws AdException {

        List<Long> unitIds = request.getUnitIts().stream()
                .map(AdUnitItRequest.UnitIt::getUnitId)
                .collect(Collectors.toList());

        if(!isRelatedUnitExits(unitIds)){
            throw new AdException(Constants.ErrorMsg.CAN_NOT_FIND_RECORD);
        }

        List<Long> ids = Collections.emptyList();
        List<AdUnitIt> unitIts = new ArrayList<>();
        if(!CollectionUtils.isEmpty(request.getUnitIts())){
            request.getUnitIts().forEach(i -> unitIts.add(
                    new AdUnitIt(i.getUnitId(), i.getItTag())
            ));

            ids = adUnitItRepository.saveAll(unitIts).stream()
                    .map(AdUnitIt::getId)
                    .collect(Collectors.toList());
        }
        return new AdUnitItResponse(ids);
    }

    @Override
    public AdUnitDistrictResponse createUnitDistrict(AdUnitDistrictRequest request) throws AdException {

        List<Long> unitIds = request.getUnitDistricts().stream()
                .map(AdUnitDistrictRequest.UnitDistrict::getUnitId)
                .collect(Collectors.toList());

        if(!isRelatedUnitExits(unitIds)){
            throw new AdException(Constants.ErrorMsg.CAN_NOT_FIND_RECORD);
        }

        List<Long> ids = Collections.emptyList();
        List<AdUnitDistrict> unitDistricts = new ArrayList<>();
        if(!CollectionUtils.isEmpty(request.getUnitDistricts())){
            request.getUnitDistricts().forEach(i -> unitDistricts.add(
                    new AdUnitDistrict(i.getUnitId(), i.getProvince(), i.getCity())
            ));

            ids = adUnitDistrictRepository.saveAll(unitDistricts).stream()
                    .map(AdUnitDistrict::getId)
                    .collect(Collectors.toList());
        }

        return new AdUnitDistrictResponse(ids);
    }

    @Override
    public CreativeUnitResponse createCreativeUnit(CreativeUnitRequest request) throws AdException {

        List<Long> unitIds = request.getUnitItems().stream()
                .map(CreativeUnitRequest.CreativeUnitItem::getUnitId)
                .collect(Collectors.toList());

        List<Long> creativeIds = request.getUnitItems().stream()
                .map(CreativeUnitRequest.CreativeUnitItem::getCreativeId)
                .collect(Collectors.toList());

        if(!(isRelatedUnitExits(unitIds) && isRelatedCreativeExist(creativeIds))){
            throw new AdException(Constants.ErrorMsg.REQUEST_PARAM_ERROR);
        }

        List<CreativeUnit> creativeUnits = new ArrayList<>();
        request.getUnitItems().forEach(i -> creativeUnits.add(
                new CreativeUnit(i.getCreativeId(), i.getUnitId())
        ));

        List<Long> ids = creativeUnitRepository.saveAll(creativeUnits)
                .stream()
                .map(CreativeUnit::getId)
                .collect(Collectors.toList());

        return new CreativeUnitResponse(ids);
    }

    private boolean isRelatedUnitExits(List<Long> unitIds){

        if(CollectionUtils.isEmpty(unitIds)){
            return false;
        }

        return adUnitrepository.findAllById(unitIds).size() == new HashSet<>(unitIds).size();
    }

    private boolean isRelatedCreativeExist(List<Long> creativeIds){

        if(CollectionUtils.isEmpty(creativeIds)){
            return false;
        }

        return creativeRepository.findAllById(creativeIds).size() == new HashSet<>(creativeIds).size();
    }
}
